<!DOCTYPE html>
<html>
<head>
    <title>Undulator Diagram</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: white;
        }
    </style>
</head>
<body>
<canvas id="physicsCanvas" width="800" height="400"></canvas>
<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // --- Style and Parameter Definitions ---
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'black';
    ctx.lineWidth = 2;

    const y_axis = 200;
    const y_wave_center = 100;
    const wave_amplitude = 18;

    const mag_w = 45;
    const mag_h = 35;
    const mag_gap_x = 25; // Horizontal gap between magnets
    const mag_gap_y = 10; // Vertical gap from magnet to axis
    const block_width = mag_w + mag_gap_x; // Total width of one magnet unit (magnet + gap)
    const num_magnets = 8;
    const start_x = 100;

    // --- Helper function to draw an arrowhead ---
    function drawArrowHead(ctx, x, y, angle, headlen = 10) {
        ctx.save();
        ctx.translate(x, y);
        ctx.rotate(angle);
        ctx.beginPath();
        ctx.moveTo(0, 0);
        ctx.lineTo(-headlen, -headlen / 2.5);
        ctx.moveTo(0, 0);
        ctx.lineTo(-headlen, headlen / 2.5);
        ctx.stroke();
        ctx.restore();
    }

    // --- Main Drawing Logic ---

    // 1. Draw the magnets and their labels
    ctx.font = 'bold 22px sans-serif';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    for (let i = 0; i < num_magnets; i++) {
        const x = start_x + i * block_width;
        // Top magnet
        ctx.strokeRect(x, y_axis - mag_gap_y - mag_h, mag_w, mag_h);
        // Bottom magnet
        ctx.strokeRect(x, y_axis + mag_gap_y, mag_w, mag_h);

        // Labels
        const topLabel = (i % 2 === 0) ? 'N' : 'S';
        const bottomLabel = (i % 2 === 0) ? 'S' : 'N';
        ctx.fillText(topLabel, x + mag_w / 2, y_axis - mag_gap_y - mag_h / 2);
        ctx.fillText(bottomLabel, x + mag_w / 2, y_axis + mag_gap_y + mag_h / 2);
    }

    // 2. Draw the central axis
    ctx.save();
    const axis_start_x = 70;
    const axis_end_x = start_x + num_magnets * block_width - mag_gap_x + 20;
    ctx.setLineDash([8, 8]);
    ctx.beginPath();
    ctx.moveTo(axis_start_x, y_axis);
    ctx.lineTo(axis_end_x, y_axis);
    ctx.stroke();
    ctx.restore(); // Restore to solid line for arrowhead
    drawArrowHead(ctx, axis_end_x, y_axis, 0);

    // 3. Draw the 'c' label and arrow
    ctx.font = 'italic 20px serif';
    ctx.fillText('c', 20, y_axis);
    ctx.beginPath();
    ctx.moveTo(35, y_axis);
    ctx.lineTo(60, y_axis);
    ctx.stroke();
    drawArrowHead(ctx, 60, y_axis, 0);

    // 4. Draw the dimension line for 'd'
    const d_y = y_axis + mag_gap_y + mag_h + 30;
    const d_x1 = start_x + 2 * block_width;
    const d_x2 = start_x + 4 * block_width;
    ctx.beginPath();
    // Horizontal line
    ctx.moveTo(d_x1, d_y);
    ctx.lineTo(d_x2, d_y);
    // Vertical ticks
    ctx.moveTo(d_x1, d_y - 8);
    ctx.lineTo(d_x1, d_y + 8);
    ctx.moveTo(d_x2, d_y - 8);
    ctx.lineTo(d_x2, d_y + 8);
    ctx.stroke();
    ctx.font = 'italic 20px serif';
    ctx.fillText('d', (d_x1 + d_x2) / 2, d_y + 20);

    // 5. Draw the wavy electron path
    ctx.save();
    const path_start_x = 50;
    const path_end_x = start_x + num_magnets * block_width - mag_gap_x + 20;
    const wave_period = 2 * block_width; // Corresponds to period 'd'
    const k = (2 * Math.PI) / wave_period;
    const phase_shift = start_x + mag_w / 2;

    const path_func = (x) => y_wave_center - wave_amplitude * Math.cos(k * (x - phase_shift));

    ctx.setLineDash([8, 6]);
    ctx.beginPath();
    let y_start = path_func(path_start_x);
    ctx.moveTo(path_start_x, y_start);

    for (let x = path_start_x + 1; x <= path_end_x; x++) {
        ctx.lineTo(x, path_func(x));
    }
    ctx.stroke();
    ctx.restore(); // Restore to solid line for arrowheads

    // Add arrowheads to the path
    // Start arrowhead
    let y_start_next = path_func(path_start_x + 1);
    let angle_start = Math.atan2(y_start_next - y_start, 1);
    drawArrowHead(ctx, path_start_x, y_start, angle_start);

    // End arrowhead
    let y_end = path_func(path_end_x);
    let y_end_prev = path_func(path_end_x - 1);
    let angle_end = Math.atan2(y_end - y_end_prev, 1);
    drawArrowHead(ctx, path_end_x, y_end, angle_end);

    // 6. Draw the figure caption
    ctx.font = '18px serif';
    ctx.textAlign = 'center';
    ctx.fillText('Fig. 3.5', canvas.width / 2, 370);

</script>
</body>
</html>